﻿using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

/// <summary>
/// 企业微信回调校验
/// </summary>
public static class WorkWechatCryptoHelper
{
    /// <summary>
    /// 校验签名
    /// </summary>
    public static bool VerifySignature(string msgSignature, string token, string timestamp, string nonce, string encrypt)
    {
        // 1. 按token、timestamp、nonce、encrypt的顺序拼接字符串
        string[] arr = { token, timestamp, nonce, encrypt };
        Array.Sort(arr);
        string combined = string.Join("", arr);

        // 2. SHA1哈希计算
        using (var sha1 = SHA1.Create())
        {
            byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(combined));
            string computedSignature = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();

            // 3. 对比签名
            return computedSignature == msgSignature.ToLower();
        }
    }

    /// <summary>
    /// AES解密（企业微信ECC模式）
    /// </summary>
    public static string AesDecrypt(string encryptText, string encodingAesKey, string corpId)
    {
        // 1. EncodingAESKey Base64解码
        byte[] aesKey = Convert.FromBase64String(encodingAesKey + "="); // 补全4的倍数长度
        byte[] encryptBytes = Convert.FromBase64String(encryptText);

        // 2. AES解密（模式：CBC，填充：PKCS7，IV：前16字节）
        using (var aes = Aes.Create())
        {
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = aesKey;
            aes.IV = aesKey.Take(16).ToArray(); // IV为AESKey前16字节

            using (var decryptor = aes.CreateDecryptor())
            {
                byte[] plainBytes = decryptor.TransformFinalBlock(encryptBytes, 0, encryptBytes.Length);

                // 3. 解析明文结构（random(16字节) + msgLen(4字节) + msg + corpId）
                int msgLen = BitConverter.ToInt32(plainBytes.Skip(16).Take(4).ToArray(), 0);
                string msg = Encoding.UTF8.GetString(plainBytes.Skip(20).Take(msgLen).ToArray());
                string decryptedCorpId = Encoding.UTF8.GetString(plainBytes.Skip(20 + msgLen).ToArray());

                // 4. 校验CorpId（防止篡改）
                if (decryptedCorpId != corpId)
                {
                    throw new Exception("CorpId校验失败，消息可能被篡改");
                }

                return msg;
            }
        }
    }

    /// <summary>
    /// 准备企业微信AES加密的参数
    /// </summary>
    /// <param name="actualMsg">要加密的实际消息（如被动回复的XML）</param>
    /// <param name="encodingAesKey">企业微信后台配置的EncodingAESKey</param>
    /// <param name="corpId">企业微信CorpId</param>
    /// <returns>加密所需的参数（明文、Key、IV）</returns>
    public static (string encryptedPlainText, byte[] key, byte[] iv) PrepareWechatEncryptParams(
        string actualMsg,
        string encodingAesKey,
        string corpId)
    {
        // 步骤1：生成16字节随机字符串（用于混淆）
        byte[] randomBytes = new byte[16];
        new Random().NextBytes(randomBytes);
        string randomStr = Encoding.UTF8.GetString(randomBytes);

        // 步骤2：获取实际消息的字节长度（转4字节大端序，企业微信要求）
        byte[] msgBytes = Encoding.UTF8.GetBytes(actualMsg);
        byte[] msgLenBytes = BitConverter.GetBytes(msgBytes.Length);
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(msgLenBytes); // 转为大端序（企业微信要求）
        }
        string msgLenStr = Encoding.UTF8.GetString(msgLenBytes);

        // 步骤3：拼接企业微信要求的完整明文
        string fullPlainText = $"{randomStr}{msgLenStr}{actualMsg}{corpId}";

        // 步骤4：处理Key（EncodingAESKey Base64解码）
        byte[] key = Convert.FromBase64String(encodingAesKey + "="); // 补"="确保Base64解码长度正确

        // 步骤5：处理IV（固定为Key的前16字节）
        byte[] iv = key.Take(16).ToArray();

        return (fullPlainText, key, iv);
    }

    /// <summary>
    /// 调用通用Encrypt方法，实现企业微信消息加密
    /// </summary>
    /// <param name="replyMsg">被动回复的消息内容（如XML格式）</param>
    /// <param name="encodingAesKey">企业微信EncodingAESKey</param>
    /// <param name="corpId">企业微信CorpId</param>
    /// <returns>企业微信可用的Base64加密字符串</returns>
    public static string WechatAesEncrypt(string replyMsg, string encodingAesKey, string corpId)
    {
        // 步骤1：准备符合企业微信规则的参数
        var (fullPlainText, key, iv) = PrepareWechatEncryptParams(replyMsg, encodingAesKey, corpId);

        // 步骤2：调用你的通用Encrypt方法（注意：需确保你的方法返回Base64编码后的字符串）
        string encryptedResult = AesCbcHelper.Encrypt(fullPlainText, key, iv);

        // 步骤3：直接返回结果（企业微信要求加密后内容为Base64格式）
        return encryptedResult;
    }
}